home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / comm / tcp / AmiTCPsmtpd.lha / smtpd.c < prev    next >
C/C++ Source or Header  |  1994-02-06  |  15KB  |  828 lines

  1. RCS_ID_C= "$Id: smtpd.c,v 1.7 1994/02/06 10:07:33 gwalter Rel $";
  2. /*
  3.  * smtpd.c --- an example of TCP daemon for AmiTCP/IP
  4.  *
  5.  * $Log: smtpd.c,v $
  6.  * Revision 1.7  1994/02/06  10:07:33  gwalter
  7.  * Changed to use TCPLog from logger.lib
  8.  * Line buffer size increased
  9.  *
  10.  * Revision 1.6  1994/02/01  19:49:35  gwalter
  11.  * Parameters added, tidying
  12.  *
  13.  * Revision 1.5  1994/01/09  14:01:27  gwalter
  14.  * Timeouts, improved logging
  15.  *
  16.  * Revision 1.3  1993/12/30  16:38:18  gwalter
  17.  * Changed to display QUIT command from client.
  18.  *
  19.  * Revision 1.2  1993/12/21  09:44:14  gwalter
  20.  * Reference to pathnames.h removed
  21.  *
  22.  * Revision 1.1  1993/12/21  09:34:12  gwalter
  23.  * Initial revision
  24.  *
  25.  * Revision 1.1  1993/12/05  18:10:02  gwalter
  26.  * Initial revision
  27.  *
  28.  *
  29.  */
  30.  
  31. #include "smtpd_rev.h"
  32.  
  33. char ApplicationID[] = "SMTPD";
  34.  
  35. const char version[] = VERSTAG;
  36.  
  37. char copyright[] =
  38.   "Copyright © 1993 Graham Walter, <amitcp@gwalter.demon.co.uk>\n"
  39.   "20 Kingstable St, Eton, Berks, England.\n";
  40.  
  41. #ifdef AMIGA
  42. #if __SASC
  43. #include <proto/socket.h>
  44. #include <proto/dos.h>
  45. #include <clib/exec_protos.h>
  46. #include <pragmas/exec_sysbase_pragmas.h>
  47. #elif __GNUC__
  48. #include <inline/socket.h>
  49. #include <inline/exec.h>
  50. #else
  51. #include <clib/socket_protos.h>
  52. #endif
  53. #endif /* AMIGA */
  54.  
  55. #include <errno.h>
  56. #include <netdb.h>
  57.  
  58. #include <sys/param.h>
  59. #include <sys/socket.h>
  60. #include <sys/ioctl.h>
  61. #include <netinet/in.h>
  62. #include <netdb.h>
  63. #include <sys/syslog.h>
  64.  
  65. #include <signal.h>
  66.  
  67. #include <dos/dos.h>
  68. #include <exec/execbase.h>
  69. #include <dos/var.h>
  70. #include <dos/dostags.h>
  71.  
  72. #include <stdlib.h>
  73. #include <stdio.h>
  74. #include <string.h>
  75. #include <time.h>
  76. #include <inetdlib.h>
  77.  
  78. #include <lineread.h>
  79.  
  80. #include "smtpd.h"
  81.  
  82. char * gethostname( char * host, long size );
  83.  
  84. extern struct ExecBase *SysBase;
  85.  
  86. BPTR Stdin = NULL;
  87. BPTR Stdout = NULL;
  88. BPTR Stderr = NULL;
  89.  
  90. char ** LocalHostAliases;
  91. char * LocalHost;
  92. char PeerName[MAX_HOSTLEN+1];
  93.  
  94. char * LogFileName;
  95. char * RMailCommand = RMAIL_TEMPLATE;
  96.  
  97. int ErrorCount;
  98.  
  99. void
  100. _STIdosStdio(void)
  101. {
  102.   struct Process *p = (struct Process *)SysBase->ThisTask;
  103.  
  104.   Stdin = p->pr_CIS;
  105.   Stdout = p->pr_COS;
  106.   Stderr = p->pr_CES ? p->pr_CES : Stdout;
  107. }
  108.  
  109. /* Handle various mailer errors. */
  110.  
  111. static char * ApplicationErrorMsgs[] =
  112. {
  113.     "" /*"Network fault"*/,
  114.     MAILERR_TEXT_BAD_RESPONSE,
  115.     MAILERR_TEXT_NOTEMP,
  116.     MAILERR_TEXT_INVALID_COMMAND,
  117.     MAILERR_TEXT_SEND_ERROR,
  118.     MAILERR_TEXT_NO_MEMORY,
  119.     MAILERR_TEXT_EXPECTING_HELO,
  120.     MAILERR_TEXT_TEMPWRITE,
  121.     MAILERR_TEXT_CONNECTION_LOST,
  122.     MAILERR_TEXT_SELECT,
  123.     MAILERR_TEXT_TIMEOUT,
  124.     MAILERR_TEXT_LOCALHOST,
  125.     MAILERR_TEXT_INVALID_ARGUMENTS,
  126.     MAILERR_TEXT_NO_DELIVERY,
  127.     MAILERR_TEXT_NOT_DELIVERED,
  128.     MAILERR_TEXT_COMMAND_REJECT
  129. };
  130.  
  131. void
  132. MailError(int    Type, char * info )
  133. {
  134.     char * errortext;
  135.     char syserrorbuffer[SHORT_BUFFER_LEN];
  136.  
  137.     if( Type == 0 )
  138.     {
  139.         char * syserrortext;
  140.  
  141.         if( errno < __sys_nerr)
  142.             syserrortext = (UBYTE *)__sys_errlist[errno];
  143.         else 
  144.             syserrortext = (UBYTE *)__sys_errlist[0];
  145.  
  146.         sprintf( syserrorbuffer, "%s %%s", syserrortext );
  147.         errortext = syserrorbuffer;
  148.     }
  149.     else
  150.     {
  151.         if( Type < sizeof( ApplicationErrorMsgs ) / sizeof( ApplicationErrorMsgs[0] ) )
  152.             errortext = ApplicationErrorMsgs[Type];
  153.         else
  154.             errortext = MAILERR_TEXT_UNKNOWN_ERROR;
  155.     }
  156.  
  157.     TCPLog( LOG_ERR, errortext, (info) ? info: "" );
  158.  
  159.     if( ++ErrorCount >= MAX_ERRORS )
  160.     {
  161.         TCPLog( LOG_CRIT, MAILERR_TEXT_ABORTING_MAXERRS );
  162.  
  163.         exit( 20 );
  164.     }
  165. }
  166.  
  167. /* Get the date, and format it for RFC822. */
  168.  
  169. char *
  170. GetDate( void )
  171. {
  172.     time_t        clock;
  173.  
  174.     clock = time(NULL);
  175.  
  176.     return ctime(&clock);
  177. }
  178.  
  179. char **
  180. gethostent( void )
  181. {
  182.     char ** nameblock;
  183.     char ** alias;
  184.     char local[STD_BUFFER_LEN];
  185.     struct hostent * hostent;
  186.     int i;
  187.  
  188.     if( nameblock = calloc( MAX_ALIASES+2, sizeof( char * ) ) )
  189.     {
  190.         gethostname( local, sizeof( local ) );
  191.  
  192.         if( hostent = gethostbyname( local ) )
  193.         {
  194.             nameblock[0] = hostent->h_name;
  195.             
  196.             for( i = 1, alias = hostent->h_aliases; *alias; alias++ )
  197.             {
  198.                 nameblock[i++] = strdup( *alias );
  199.  
  200.                 if( i > MAX_ALIASES )
  201.                     break;
  202.             }
  203.         }
  204.         else
  205.         {
  206.             free( nameblock );
  207.             nameblock = NULL;
  208.         }
  209.     }
  210.     else
  211.         MailError( MAILERR_NO_MEMORY, NULL );
  212.  
  213.     if( ! nameblock )
  214.         MailError( MAILERR_LOCALHOST, NULL );
  215.  
  216.     return( nameblock );
  217. }
  218.  
  219. int
  220. StripCRLF( char * buffer )
  221. {
  222.     int len;
  223.  
  224.     len = strlen( buffer );
  225.     
  226.     if( len && ( buffer[len-1] == '\n' ) )
  227.         buffer[--len] = '\0';
  228.  
  229.     if( len && ( buffer[len-1] == '\r' ) )
  230.         buffer[--len] = '\0';
  231.  
  232.     return( len );
  233. }
  234.  
  235. /* Get a line from a socket */
  236.  
  237. int
  238. GetLine( int s, char * buffer, struct LineRead * rl )
  239. {
  240. static    int len = 0;
  241.     int nfds;
  242.     fd_set readfds;
  243.     fd_set excepfds;
  244. static    struct timeval timeout = { TIMEOUT, 0 };
  245.  
  246.     for( ;; )
  247.     {
  248.         if( ! len )
  249.         {
  250.             FD_ZERO( &readfds );
  251.             FD_SET(s, &readfds );
  252.  
  253.             FD_ZERO( &excepfds );
  254.             FD_SET(s, &excepfds );
  255.  
  256.             if( (nfds = select(s + 1, &readfds, NULL, &excepfds, &timeout )) < 0)
  257.             {
  258.                     MailError( MAILERR_SELECT, "GetLine" );
  259.                     return( -1 );
  260.                 }
  261.  
  262.             if( ! nfds )
  263.             {
  264.                 MailError( MAILERR_TIMEOUT, "GetLine" );
  265.                 return( -1 );
  266.             }
  267.         }
  268.  
  269.         if( ( len = lineRead( rl ) ) != 0 )
  270.             break;
  271.  
  272.         if( ! rl->rl_Line )
  273.         {
  274.             return( -1 );    /* EOF */
  275.         }
  276.  
  277.     }
  278.  
  279.       if( len <= 0 )
  280.       {
  281.               MailError( 0, "GetLine" );
  282.               return( -1 );
  283.           }
  284.  
  285.     strcpy( buffer, rl->rl_Line );
  286.  
  287.     return( StripCRLF( buffer ) );
  288. }
  289.  
  290. /* Simply send some text down the socket; check the write succeeds, but don't
  291. check for any response. */
  292.  
  293. int
  294. SendText(int s, char *Text)
  295. {
  296.     if( send( s, Text, strlen(Text), 0 ) != strlen(Text) )
  297.     {
  298.         MailError( 0, "SendText" );
  299.         return( 0 );
  300.     }
  301.  
  302.     return 1;
  303. }
  304.  
  305. int
  306. isCommand( char * buffer, char * Command )
  307. {
  308.     int len = strlen( Command );
  309.     int Status = FALSE;
  310.  
  311.     if( ( strnicmp( buffer, Command, len ) == 0 )
  312.      && ( ( isspace( buffer[len] ) )
  313.        || ( buffer[len] == '\0' ) ) )
  314.     {
  315.         Status = TRUE;
  316.     }
  317.  
  318.     return( Status );
  319. }
  320.  
  321. int StoreRecipient( char * to, char * from )
  322. {
  323.     char * cp;
  324.     char * host;
  325.     char ** alias;
  326.     int length;
  327.  
  328.     if( ! ( cp = strchr( from, ':' ) ) )
  329.         return( FALSE );
  330.  
  331.     from = cp + 1;
  332.  
  333.     if( *from == '<' )
  334.     {
  335.         if( ! ( cp = strchr( from, '>' ) ) )
  336.             return( FALSE );
  337.  
  338.         from ++;
  339.         length = cp - from;
  340.     }
  341.     else
  342.     {
  343.         length = stcarg( from, " \r\n" );
  344.     }
  345.  
  346.     memcpy( to, from, length );
  347.     to[length] = '\0';
  348.  
  349.     if( strchr( to, '%' ) )            /* need to forward ? */
  350.         return( FALSE );
  351.  
  352.     if( ! ( cp = strchr( to, '@' ) ) )    /* no host specified */
  353.         return( TRUE );
  354.  
  355.     host = cp + 1;
  356.     length = strlen( host );
  357.     *cp = '\0';
  358.  
  359.     for( alias = LocalHostAliases; *alias; alias++ )
  360.     {
  361.         if( stricmp( host, *alias ) == 0 ) /* this host */
  362.             return( TRUE );
  363.  
  364.         if( ( strnicmp( host, *alias, length ) == 0 )
  365.          && ( (*alias)[length] == '.' ) )
  366.              return( TRUE );           /* valid abbreviation */
  367.     }
  368.  
  369.     return( FALSE );
  370. }
  371.  
  372. int
  373. LogMail( ULONG fh )
  374. {
  375.     ULONG logfh;
  376. static  buffer[STD_BUFFER_LEN];
  377.     int len;
  378.  
  379.     if( ! (logfh = Open( LogFileName, MODE_READWRITE ) ) )
  380.     {
  381.         TCPLog( LOG_WARNING, MAILERR_TEXT_LOG_OPEN_FAIL );
  382.         return( 1 );
  383.     }
  384.  
  385.     Seek( logfh, 0, OFFSET_END );
  386.  
  387.     Seek( fh, 0, OFFSET_BEGINNING );
  388.  
  389.     while( len = Read( fh, buffer, sizeof( buffer ) ) )
  390.     {
  391.         Write( logfh, buffer, len );
  392.     }
  393.  
  394.     Write( logfh, "\n", 1 );
  395.  
  396.     Close( logfh );
  397.  
  398.     return( 0 );
  399. }
  400.  
  401. int
  402. PassMailToRecipients( int s, struct LineRead * rl, char * From, ULONG rfh )
  403. {
  404.     char * tfile;
  405.     ULONG tfh;
  406.     char * line;
  407.     char * reply;
  408.     char buffer[STD_BUFFER_LEN];
  409.     char Recipient[STD_BUFFER_LEN];
  410.     long len;
  411.     int SentCount;
  412.     int status = 0;
  413.  
  414.     if( ! rfh )
  415.     {
  416.         SendText( s, SMTP_RESPONSE_NO_RECIPIENTS );
  417.  
  418.         TCPLog( LOG_WARNING, MAILERR_TEXT_NO_RECIPIENTS );
  419.  
  420.         return( 0 );
  421.     }
  422.  
  423.     tfile = tmpnam( NULL );
  424.     if( ! ( tfh = Open( tfile, MODE_NEWFILE ) ) )
  425.     {
  426.           MailError( MAILERR_NOTEMP, "Data" );
  427.  
  428.           return( 1 );
  429.     }
  430.  
  431.     strcpy( buffer, GetDate() );
  432.  
  433.     FPrintf( tfh, "From %s %s", From, buffer ); 
  434.  
  435.     FPrintf( tfh, "Return-Path: <%s>\n", From );
  436.  
  437.     FPrintf( tfh, "Received: ") ;
  438.     FPrintf( tfh, "from %s ", PeerName );
  439.     FPrintf( tfh, "by %s with SMTP\n\tid AA%05ld; %s",
  440.             LocalHost, 1, buffer );
  441.  
  442.  
  443.     if( ! SendText(s, SMTP_RESPONSE_RECEIVING ) )
  444.     {
  445.           Close( tfh );
  446.           return( 1 );
  447.     }
  448.  
  449.     for(;;)
  450.     {
  451.         if( ( len = GetLine( s, buffer, rl ) ) < 0 )
  452.         {
  453.             MailError( 0, "Getting Mail Item Data" );
  454.             Close( tfh );
  455.             return( 1 );
  456.         }
  457.  
  458.         line = buffer;
  459.  
  460.         if( line[0] == '.' )
  461.         {
  462.             if( line[1] == '\0' )
  463.             {
  464.                 break;
  465.             }
  466.  
  467.             line++;
  468.         }
  469.  
  470.         FPrintf( tfh, "%s\n", line );
  471.     }
  472.  
  473.     Flush( tfh );
  474.  
  475.     if( LogFileName )
  476.         LogMail( tfh );
  477.  
  478.     Close( tfh );
  479.  
  480.     Seek( rfh, 0, OFFSET_BEGINNING );
  481.  
  482.     SentCount = 0;
  483.  
  484.     while( status == 0 
  485.         && ( FGets( rfh, Recipient, sizeof( Recipient ) - 1 ) > 0 ) )
  486.     {
  487.         StripCRLF( Recipient );
  488.  
  489.         sprintf( buffer, RMailCommand, tfile, Recipient );
  490.         if( SystemTags( buffer, TAG_DONE ) == 0 )
  491.             SentCount++;
  492.         else
  493.                MailError( MAILERR_NO_DELIVERY, Recipient );
  494.     }
  495.  
  496.     if( SentCount )
  497.     {
  498.         DeleteFile( tfile );
  499.  
  500.         reply = SMTP_RESPONSE_OK;
  501.     }
  502.     else
  503.     {
  504.         MailError( MAILERR_NOT_DELIVERED, tfile );
  505.  
  506.         reply = SMTP_RESPONSE_NO_DELIVERY;
  507.     }
  508.  
  509.     if( ! SendText(s, reply ) )
  510.         return( 1 );
  511.  
  512.     return( 0 );
  513. }
  514.  
  515. int ReadMailItem( int s, struct LineRead * rl )
  516. {
  517.     char * From;
  518.     char * cp;
  519.     long len;
  520.     char * buffer;
  521.     char Recipient[STD_BUFFER_LEN] = "";
  522.     char rfname[L_tmpnam];
  523.     ULONG rfh = NULL;
  524.     int status = 0;
  525.  
  526.     if( ! ( buffer = malloc( MAX_LINE_LENGTH ) ) )
  527.     {
  528.         return( 1 );
  529.     }
  530.  
  531.     strcpy( buffer, rl->rl_Line + strlen( "MAIL FROM:" ) );
  532.     if( buffer[0] == '<' )
  533.     {
  534.         if( cp = strchr( buffer, '>' ) )
  535.             *cp = '\0';
  536.         cp = buffer + 1;
  537.     }
  538.     else cp = buffer;
  539.  
  540.     StripCRLF( buffer );
  541.  
  542.     From = strdup( cp );
  543.  
  544.     if( ! SendText( s, SMTP_RESPONSE_OK ) )
  545.     {
  546.         free( buffer );
  547.         free( From );
  548.         return( 1 );
  549.     }
  550.  
  551.     for(;;)
  552.     {
  553.         if( ( len = GetLine( s, buffer, rl ) ) < 0 )
  554.         {
  555.             status = 1;
  556.             break;
  557.         }
  558.  
  559.         if( isCommand( buffer, SMTP_COMMAND_RCPT ) )
  560.         {
  561.             char * reply;
  562.  
  563.             if( StoreRecipient( Recipient, buffer ) )
  564.             {
  565.                reply = SMTP_RESPONSE_OK;
  566.  
  567.                if( ! rfh )
  568.                {
  569.                 if( ! ( rfh = Open( tmpnam( rfname ), MODE_NEWFILE ) ) )
  570.                 {
  571.                     MailError( MAILERR_NOTEMP, "Recipients" );
  572.                     status = 1;
  573.                     break;
  574.                 }
  575.                }
  576.  
  577.                if( FPrintf( rfh, "%s\n", Recipient ) <= 0 )
  578.                {
  579.                 MailError( MAILERR_TEMPWRITE, "Recipients (w)" );
  580.                 reply = SMTP_RESPONSE_NOWRITE_RECIPIENT;
  581.                }
  582.             }
  583.             else
  584.                 reply = SMTP_RESPONSE_WHOTHEHECK;
  585.  
  586.             if( reply[0] != '2' )
  587.                 MailError( MAILERR_COMMAND_REJECT, buffer );
  588.  
  589.             if( ! SendText(s, reply ) )
  590.             {
  591.                   status = 1;
  592.                   break;
  593.             }
  594.         }
  595.         else if( isCommand( buffer, SMTP_COMMAND_RSET ) )
  596.         {
  597.             TCPLog( LOG_INFO, buffer );
  598.  
  599.             if( ! SendText(s, SMTP_RESPONSE_OK ) )
  600.             {
  601.                   status = 1;
  602.                   break;
  603.             }
  604.  
  605.             break;
  606.         }
  607.         else if( isCommand( buffer, SMTP_COMMAND_NOOP ) )
  608.         {
  609.             if( ! SendText(s, SMTP_RESPONSE_OK ) )
  610.             {
  611.                   status = 1;
  612.                   break;
  613.             }
  614.         }
  615.         else if( isCommand( buffer, SMTP_COMMAND_DATA ) )
  616.         {
  617.             if( ! rfh )
  618.             {
  619.                 SendText( s, SMTP_RESPONSE_NO_RECIPIENTS );
  620.  
  621.                 TCPLog( LOG_WARNING, MAILERR_TEXT_NO_RECIPIENTS );
  622.  
  623.                 break;
  624.             }
  625.  
  626.             Flush( rfh );
  627.  
  628.             status = PassMailToRecipients( s, rl, From, rfh );
  629.  
  630.             break;
  631.         }
  632.         else if( isCommand( buffer, SMTP_COMMAND_QUIT ) )
  633.         {
  634.             TCPLog( LOG_INFO, buffer );
  635.  
  636.             sprintf( buffer, SMTP_RESPONSE_CLOSING, LocalHost );
  637.  
  638.               SendText( s, buffer );
  639.  
  640.                   return( 1 );
  641.         }
  642.         else
  643.         {
  644.             MailError( MAILERR_INVALID_COMMAND, buffer );
  645.             status = 1;
  646.                   break;
  647.         }
  648.     }
  649.  
  650.     if( rfh )
  651.     {
  652.         Close( rfh );
  653.         DeleteFile( rfname );
  654.     }
  655.  
  656.     free( buffer );
  657.     free( From );
  658.     return( status );
  659. }
  660.  
  661. int
  662. main(int argc, char **argv)
  663. {
  664.     long len;
  665.     int s = server_socket;
  666.  
  667. #ifdef LOGGING
  668. #include <netinet/in.h>
  669.     struct sockaddr_in sin;
  670.     int sval;
  671. #endif
  672.     char buffer[STD_BUFFER_LEN];
  673.     struct LineRead * rl;
  674.  
  675.     struct RDArgs    *Args;
  676.     long        ArgRes[ARGCOUNT];
  677.     register int    i = 0;
  678.  
  679.     for( i = 0; i < ARGCOUNT; ArgRes[i++] = NULL )
  680.         ;
  681.  
  682.     /* Look at command line arguments. */
  683. #ifdef DEBUG
  684.     TCPLog( LOG_DEBUG, "starting, %ld arguments", argc );
  685.     if( argc )
  686.         TCPLog( LOG_DEBUG, "1st argument:%s", argv[0] );
  687. #endif
  688.  
  689.     if(!(Args = ReadArgs((UBYTE *)SMTPD_TEMPLATE, ArgRes, NULL)))
  690.     {
  691.         MailError( MAILERR_INVALID_ARGUMENTS, NULL ); 
  692.         return( 20 );
  693.     }
  694.  
  695.     if( ArgRes[ARG_LOGFILE] )
  696.     {
  697.         LogFileName = strdup( (char*)(ArgRes[ARG_LOGFILE]) );
  698. #ifdef DEBUG
  699.         TCPLog( LOG_DEBUG, "LogFile set to %s", LogFileName );
  700. #endif
  701.     }
  702.  
  703.     if( ArgRes[ARG_RMAIL] )
  704.     {
  705.         RMailCommand = strdup( (char*)(ArgRes[ARG_RMAIL]) );
  706. #ifdef DEBUG
  707.         TCPLog( LOG_DEBUG, "RMailCommand set to %s", RMailCommand );
  708. #endif
  709.     }
  710.  
  711.     FreeArgs(Args);
  712.  
  713.     if ( s == -1 )
  714.     {
  715. #ifdef STANDALONE
  716.         struct sockaddr_in sin;
  717.  
  718.         s = serveraccept( "smtp", &sin );
  719.         if ( s != -1 )
  720.         {
  721.             FPrintf( Stderr, "Accepted a connection from %s, port %ld\n",
  722.             inet_ntoa( sin.sin_addr ), sin.sin_port );
  723.         } else
  724. #endif
  725.             return 1;
  726.     }
  727.  
  728.     if( ! ( LocalHostAliases = gethostent( ) ) )
  729.         return( 1 );
  730.  
  731.     LocalHost = LocalHostAliases[0];
  732.  
  733. #ifdef LOGGING            /* unused for now */
  734.     sval = sizeof( sin );
  735.     if ( getpeername( 0, &sin, &sval ) < 0 )
  736.         fatal( "getpeername" );
  737. #endif
  738.  
  739.     if( ! ( rl = ( struct LineRead * )AllocMem( sizeof ( *rl ), 0 ) ) )
  740.     {
  741.         MailError( MAILERR_NO_MEMORY, NULL );
  742.         return( 1 );
  743.     }
  744.  
  745.     initLineRead( rl, s, /*LF_REQLF*/ 1, RL_BUFSIZE );
  746.  
  747.     sprintf( buffer, SMTP_RESPONSE_READY, LocalHost );
  748.  
  749.     if( ! SendText( s, buffer ) )
  750.         return( 1 );
  751.  
  752.     if( ( ( len = GetLine( s, buffer, rl ) ) <= strlen( SMTP_COMMAND_HELO ) + 1 )
  753.      || ( ! isCommand( buffer, SMTP_COMMAND_HELO ) ) )
  754.     {
  755.         MailError( MAILERR_EXPECTING_HELO, buffer );
  756.         return( 1 );
  757.     }
  758.  
  759.     TCPLog( LOG_INFO, buffer );
  760.  
  761.     strcpy( PeerName, buffer + strlen( SMTP_COMMAND_HELO ) + 1 );
  762.  
  763.     sprintf( buffer, SMTP_RESPONSE_OK_SUBS, LocalHost );
  764.  
  765.     if( ! SendText( s, buffer ) )
  766.         return( 1 );
  767.  
  768.   for(;;)
  769.   {
  770.     if( ( len = GetLine( s, buffer, rl ) ) < 0 )
  771.     {
  772.         MailError( MAILERR_CONNECTION_LOST, NULL );
  773.  
  774.         return( 1 );
  775.     }
  776.  
  777.     if( isCommand( buffer, SMTP_COMMAND_QUIT ) )
  778.     {
  779.         TCPLog( LOG_INFO, buffer );
  780.  
  781.         sprintf( buffer, SMTP_RESPONSE_CLOSING, LocalHost );
  782.           if( ! SendText( s, buffer ) )
  783.           {
  784.                   return( 1 );
  785.           }
  786.  
  787.         break;
  788.     }
  789.     else if( isCommand( buffer, SMTP_COMMAND_NOOP ) )
  790.     {
  791.         if( ! SendText(s, SMTP_RESPONSE_OK ) )
  792.         {
  793.               return( 1 );
  794.         }
  795.     }
  796.     else if( isCommand( buffer, SMTP_COMMAND_RSET ) )
  797.     {
  798.         if( ! SendText(s, SMTP_RESPONSE_OK ) )
  799.         {
  800.               return( 1 );
  801.         }
  802.     }
  803.     else if( isCommand( buffer, SMTP_COMMAND_MAIL ) )
  804.     {
  805.         TCPLog( LOG_INFO, buffer );
  806.  
  807.         if( ReadMailItem( s, rl ) )
  808.             return( 1 );
  809.     }
  810.     else
  811.     {
  812.         MailError( MAILERR_INVALID_COMMAND, buffer );
  813.  
  814.         if( ! SendText(s, SMTP_RESPONSE_PARDON ) )
  815.         {
  816.               return( 1 );
  817.         }
  818.     }
  819.  
  820.   }
  821.  
  822. #if 0
  823.   TCPLog( LOG_DEBUG, "Terminating normally" );
  824. #endif
  825.  
  826.   return 0;
  827. }
  828.